/*
 * v1 5/16/2011 Created Scheduler Skeleton
 * v2 5/21/2011 Filled in Constructor and basic Schedule Manipulation
 * v3 5/23/2011 Finished checkConstraints()
 * v4 5/23/2011 Fixed a broken business rule check (credit limits for teachers)
 * v5 5/29/2011 Started changes to output from checkConstraints
 * v6 5/30/2011 Finished changes to Scheduler to check different credit limits and output properly
 * v7 5/31/2011 (Michael) Fixed line 77 y = x + 1
 *              added my_feedback.setViolatedTeachingSchedule(course_violations); (ln 95)
 *              fixed checkConstraints 
 *              (was: int actual_limit = teacher_credits.get(teach))
 */
package main;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Scheduler is a class that can read an official TCSS360-format-specified
 * schedule, and check whether or not it has met the constraints imposed 
 * upon it by the system Scheduler is a part of.
 * 
 * @author C Brady Mc
 * @version 5/30/2011
 */
public class Scheduler {
    
    /**
     * Contains every line of the schedule, 
     * where each line represents a row in the schedule.
     */
    private List<Course> my_schedule;
    
    /**
     * The list of all users within the system.
     */
    private UserList my_users;
    
    /**
     * The accumulated Feedback from the schedule.
     */
    private Feedback my_feedback;
    
    /**
     * Creates a Scheduler object containing a schedule 
     * and full official list of Courses.
     * 
     * precon: the list of courses must not be null, the_users must not be null.
     * postcon: A functional Scheduler will be made.
     * @param the_courses The list of courses provided to the Scheduler.
     * @param the_users The list of all users for the quarter.
     * @throws FileNotFoundException When given a non-existent file.
     */
    public Scheduler(final List<Course> the_courses, final UserList the_users){
        my_schedule = the_courses;
        my_users = the_users;
        my_feedback = new Feedback();
    }
    
    /**
     * This method checks whether the users of the system and 
     * the rules of the system are satisfied with the schedules, 
     * and returns it's findings.
     * 
     * precon: The Scheduler object is properly constructed.
     * postcon: The returned String will contain both violated user preferences, and any violated business rules.
     * @return A List of Strings representing the constraints and preferences that were not met.
     */
    public Feedback checkConstraints(){
        
        //First, check the user preferences.
        my_feedback.setStudentFeedback(my_users.getViolatedStudentPreferences(my_schedule));
        my_feedback.setTeacherFeedback(my_users.getViolatedTeacherPreferences(my_schedule));
        my_feedback.setAdvisorFeedback(my_users.getViolatedAdvisorPreferences(my_schedule));
        
        Map<String, List<String>> course_violations = 
          new HashMap<String, List<String>>();
        
        //Now check for teachers teaching at the same time
        for(int x = 0; x < my_schedule.size(); x++){
            Course course_x = my_schedule.get(x);
            for(int y = x + 1; y < my_schedule.size(); y++){
                Course course_y = my_schedule.get(y);
                if(course_x.getProf().equals(course_y.getProf()) &&
                        course_x.getTimeblock().overlap(course_y.getTimeblock())){
                    List<String> hold = new ArrayList<String>();
                    hold.add(course_x.getTitle());
                    hold.add(course_y.getTitle());
                    
                    course_violations.put(course_x.getProf(), hold);
                }
            }
        }        
        my_feedback.setViolatedTeachingSchedule(course_violations);
        
        //Now check for teachers going over the credit limit
            //This accumulates all the teachers into a map, with their current credit hours
        Map<String, Integer> teacher_credits = new HashMap<String, Integer>();
        for(int q = 0; q < my_schedule.size(); q++){
            String teacher = my_schedule.get(q).getProf();
            Integer credits = my_schedule.get(q).getCredits();
            if(teacher_credits.containsKey(teacher)){
                teacher_credits.put(teacher, teacher_credits.get(teacher) + credits);
            } else {
                teacher_credits.put(teacher, credits);
            }
        }
        
        //Now to check each to see if they go over their limit.
        List<Teacher> hold_teach = my_users.getTeachers();
        boolean no_seperate_teacher_sets = false;
        for(Teacher teach: hold_teach){
        	if(teacher_credits.containsKey(teach.getName())){
        		no_seperate_teacher_sets = true;
        	}
        }
        if(!no_seperate_teacher_sets){
        	teacher_credits.clear();
        }
        for(Teacher teach: hold_teach){
	        if(teacher_credits.containsKey(teach.getName())){
	        	int max_limit = teach.getPrefCredits();
	         
	            int actual_limit = teacher_credits.get(teach.getName());
	            if(actual_limit <= max_limit){
	                teacher_credits.remove(teach.getName());
	            }
	        }
        }
        my_feedback.setViolatedCreditLimits(teacher_credits);
        
        return my_feedback; 
    }
    
}